home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 050 / xrf.arc / XRF1.C < prev    next >
Encoding:
C/C++ Source or Header  |  1986-04-20  |  10.0 KB  |  237 lines

  1. /*
  2.  *                      ***************
  3.  *                      * X R F 1 . C *
  4.  *                      ***************
  5.  *
  6.  * Lexical processing for C xref'er. Sifts through C source code
  7.  * and pulls out the identifiers. Recognizes reserved words and
  8.  * disregards them. Returns non-zero integer (true) if an id was
  9.  * successfully moved into 'idbuf', zero (false) if end-of-line
  10.  * was reached. I took care to test the C compiler's reaction to
  11.  * Formfeeds with respect to line numbers, and made sure the line
  12.  * numbers assigned by xrf act the same.
  13.  *
  14.  * Version V1.3          9-May-0
  15.  * Version V1.4        10-Jul-80 MM    Allow $ in identifiers, bummed code
  16.  * Version V1.5        21-Jul-80 MM    Dropped newline from ctime()
  17.  * Version V1.6        22-Jul-80 MM    '.' is not an alpha char.
  18.  * Version V1.7         4-Jan-85 MC    MDOS version
  19.  * Version V1.8         8-Jan-85 MC    Allow for 8-bit characters and 
  20.  *                                      Preprocessor commands.
  21.  * Version V1.9        12-Jan-85 MC    Identify Function calls in key and
  22.  *                                      return fixed length Symbol
  23.  * version V1.10    26-Jan-85 MC    Fix loop on #endif not recognised
  24.  *                                      & flag #include filenames.
  25.  * version V1.16        29-Mar-85 MC    Implement -f switch 
  26. */
  27.  
  28. #include <stdio.h>
  29. #include "xrf.h"
  30.  
  31. #define A 1             /* Alpha character */
  32. #define C 2             /* Start of comment possibly */
  33. #define F 3             /* Function Parameter start delimiter */
  34. #define L 4             /* Literal delimiter */
  35. #define N 5             /* Numeric character */
  36. #define P 6             /* Preprocessor Command */
  37. #define S 7             /* Space character */
  38. #define Z 9             /* End of string */
  39.  
  40. #define NRW  28          /* # reserved words */
  41. #define NRPW 7           /* # preprocessor words */
  42.  
  43. static int cmtflg = 0;        /* Comment flag */
  44. static int tifflg = 0;        /* 'This Is a Function name' flag */
  45. static char ctype[] = {         /* Character action lookup */
  46.                         Z,0,0,00,0,0,0,0,0,0,0,0,0,0,0,    /* 00 - 0F*/
  47.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 10 - 1F*/
  48.                         S,0,L,P,A,0,0,L,F,0,0,0,0,0,0,C,    /* 20 - 2F*/
  49.                         N,N,N,N,N,N,N,N,N,N,0,0,0,0,0,0,    /* 30 - 3F*/
  50.                         0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,    /* 40 - 4F*/
  51.                         A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,A,    /* 50 - 5F*/
  52.                         0,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,    /* 60 - 6F*/
  53.                         A,A,A,A,A,A,A,A,A,A,A,0,0,0,0,0,    /* 70 - 7F*/
  54.                         0,0,0,0,0,0,0,0,0,,0,0,0,0,0,0,    /* 80 - 8F*/
  55.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* 90 - 9F*/
  56.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* A0 - AF*/
  57.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* B0 - BF*/
  58.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* C0 - CF*/
  59.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* D0 - DF*/
  60.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    /* E0 - EF*/
  61.                         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0     /* F0 - FF*/
  62.                       };
  63.  
  64. static char *reswrd[NRW] = {
  65.                         "auto", "break", "case", "char",
  66.                         "continue", "default", "do", "double",
  67.                         "else", "entry", "extern", "float",
  68.                         "for", "goto", "if", "int",
  69.                         "long", "register", "return", "short",
  70.                         "sizeof", "static", "struct", "switch",
  71.                         "typedef", "union", "unsigned", "while"
  72.                         };
  73. static char *respre[NRPW] = {
  74.                         "#define","#else","#endif","#if",
  75.                         "#ifdef","#ifndef","#include"
  76.                         };
  77. #define PIN 6                /* #include position */
  78.  
  79.  
  80. /*
  81.  * Scan off a non reserved identifier. Put it into 'idbuf'.
  82.  * Returns +1 if successful, 0 if end-of-line was reached.
  83.  *
  84.  */
  85.  
  86. getid()                        /* Get an identifier into idbuf */
  87. {
  88.    register char *p ;                   /* Fast scan pointer */
  89.    register char *i ;                   /* Fast id buf pointer */
  90.    register int c;                      /* Dispatch code */
  91.    register int s;                      /* start Dispatch code */
  92.    char ch;                             /* temp char hold */
  93.    char *fixup();                       /* returns updated scan pointer*/
  94.  
  95.    p = scanp;                           /* Init fast pointers */
  96.    i = idbuf;
  97.  
  98.    while ((c = *p) != 0){                /* Scan till end of string */
  99.  
  100.      if(c == '\014'){                   /* If formfeed, */
  101.          c = *p = ' ';                  /* Convert to harmless blank */
  102.          if(prnflg)newpage();           /* Force new page */
  103.          }
  104.  
  105.       if (cmtflg){                       /* If comment flag is on */
  106.          while(*p && *p++ != '*');    /* Scan to '*' or end of string */
  107.          if(*p == '/')                  /* If we found end of comment */
  108.             cmtflg = 0;                 /* Turn off comment flag */
  109.          continue;                      /* and recycle */
  110.          }
  111.  
  112.       switch(s=ctype[c]){            /* Dispatch on the type */
  113.          case P:                        /* Start of an Preprocessor command */
  114.          case A:                        /* Start of an identifier */
  115.             i = idbuf;                  /* Reset the id buffer pointer */
  116.             do
  117.                if( i < &idbuf[symbolsize] ) /* Copy into idbuf */
  118.                   *i++ = *p++;
  119.                else                     /* Unless it gets full */
  120.                   p++;
  121.             while( (c=ctype[*p]) == A || c == N ); /* While alphanumeric */
  122.  
  123.             while( i < &idbuf[NCPS] )    /* Pad idbuf with nulls to maxlen*/
  124.                *i++ = '\0';
  125.             if(s==A)                     /* if Symbol */
  126.                if(nonres(idbuf)){          /* If it's not a reserved word */
  127.                    scanp = fixup(p);       /* Update the scan pointer */
  128.                    if(funflg){if(tifflg)return 1;}
  129.                    else return (1);        /* Return with stretched success */
  130.                    }
  131.  
  132.             if(s==P)                     /* if Preprocesor command */
  133.                switch(findpr(idbuf)){
  134.                                        /* #include - use name string*/
  135.                    case PIN: while(*p&&ctype[*p]==S)p++; /*get to delim*/
  136.                              i=idbuf;               /* Reset idbuf pointer */
  137.                              if((ch=*p)=='<')ch='>';
  138.                              do{ if(i<&idbuf[symbolsie+1])*i++=*p++;
  139.                                  else p++;    /*->idbuf unless it gets full */
  140.                                }while(*p&&*p!=ch);
  141.                              *i++ = *p;             /* delim->idbuf */
  142.                                                     /* (there will be room!)*/
  143.                              while( i < &idbuf[NCPS] )
  144.                                 *i++ = '\0';    /* Pad idbuf  to maxlen*/
  145.                              scanp = fixup(p); /* Update the scan pointer */
  146.                              if(funflg)break;
  147.                              return 1; /* Return with stretched success */
  148.                    }
  149.             break;                      /* End of identifier processing */
  150.  
  151.          case N:                        /* Scan by a number string */
  152.             do p++; while( (c=ctype[*p]) == N || c == A );
  153.             break;
  154.  
  155.          case L:                        /* Scan by a literal */
  156.         while (*++p != c && *p) {    /* Scan to the matching trailing */
  157.         if (*p == '\\') p++;    /* Quote, ignoring backslash quoted */
  158.         }                /* Characters.  If not at the end */
  159.         if (*p) p++;        /* Of the line, skip to the char. */
  160.             break;            /* Following the trailing quote */
  161.  
  162.          case C:
  163.             if(*++p == '*')             /* Start a comment */
  164.               cmtflg = 1;               /* by setting comment flag */
  165.             break;
  166.  
  167.          default:                      /* Otherwise just scan it off */
  168.             p++;
  169.             break;
  170.          }                              /* End of switch statement */
  171.  
  172.       }                         /* If we exit here, end-of line. */
  173.    return(0);                   /* Return with failure indication */
  174. }
  175.  
  176.  
  177.  
  178. /*
  179.  * Search for reserved word. Return true (1) if NOT reserved word.
  180.  * Uses binary search.
  181.  */
  182.  
  183. nonres( bufp )                  /* Test if not reserved word */
  184. char *bufp;
  185.  
  186.    {
  187.    register int low ;           /* Low pointer index */
  188.    register int mid ;           /* Mid ... */
  189.   register int hi  ;           /* hi ...  */
  190.  
  191.    int cond;                    /* Condition from strcmp */
  192.  
  193.    low = 0;
  194.    hi  = NRW-1;
  195.  
  196.    while (low <= hi)
  197.       {
  198.       mid = (low + hi) / 2;
  199.       if((cond = strcmp(bufp, reswrd[mid])) < 0)
  200.          hi = mid - 1;
  201.       else if (cond > 0)
  202.          low = mid + 1;
  203.       else
  204.          return(0);             /* False, it IS reserved */
  205.       }
  206.    return(1);                   /* True, it's NOT reserved */
  207.    }
  208.  
  209. /* find preprocessor command in table & return its position */
  210. /* as an identifier                                         */
  211. findpr(kp)
  212. char *kp;
  213. { int i;
  214.   for(i=0;i<NRPW&&strcmp(kp,respre[i]);i++);
  215.   return i;
  216. }
  217.  
  218. /* make variable length <idbuf> a fixed length [CPS] key  */
  219. /* The last two chars are () if procedure, else blank     */
  220. /* return updated line buffer ptr <p>                     */
  221.  
  222.  
  223. char *fixup(p)
  224. char *p;                  /* curr pointer */
  225. { char *cp=idbuf;
  226.     tifflg=0;
  227.     while(*cp)*cp++;              /*find end of symbol */
  228.     while(ctype[*p]==S)p++;              /*get next I/P non-space (not EOL) */
  229.     if(ctype[*p]==F){*cp++='(';*cp++=')';tifflg++;} /*funct parameter start */
  230.     while(cp<&idbuf[CPS])*cp++=' ';       /*pad symbol with spaces */
  231.     *cp='\0';                             /* failsafe*/
  232.     return p;
  233. }
  234.             cmtflg = 1;               /* by setting comment flag */
  235.             break;
  236.  
  237.          default: